package io.github.cubelitblade.librarymanagementbackend.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.github.cubelitblade.librarymanagementbackend.entity.BorrowRecord;
import io.github.cubelitblade.librarymanagementbackend.entity.BorrowRecordView;
import io.github.cubelitblade.librarymanagementbackend.exception.BusinessException;
import io.github.cubelitblade.librarymanagementbackend.mapper.BorrowMapper;
import io.github.cubelitblade.librarymanagementbackend.mapper.BorrowViewMapper;
import io.github.cubelitblade.librarymanagementbackend.utils.BorrowStatus;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;

@Service
public class BorrowService extends ServiceImpl<BorrowMapper, BorrowRecord> {
    private final BorrowViewMapper borrowViewMapper;

    BorrowService(BorrowViewMapper borrowViewMapper) {
        this.borrowViewMapper = borrowViewMapper;
    }


    /**
     * 插入借阅记录。
     *
     * @param userId 用户ID。
     * @param bookId 书籍ID。
     * @return 如果数据库操作成功，则返回所插入的记录实体。
     */
    public BorrowRecord borrowBook(Integer userId, Integer bookId) {
        if (findActiveBorrowRecord(userId, bookId) != null) {
            throw BusinessException.borrowRecordStatusConflict();
        }

        LocalDate now = LocalDate.now();
        BorrowRecord borrowRecord = new BorrowRecord(
                null,
                userId,
                bookId,
                now,
                null,
                now.plusDays(30),
                BorrowStatus.BORROWING
        );

        if (!this.save(borrowRecord)) {
            throw BusinessException.databaseError();
        }

        return borrowRecord;
    }

    /**
     * 获取用户ID对应的借阅记录列表。
     *
     * @param userId 待查询的用户ID。
     * @return 用户所对应用借阅记录列表。
     */
    public List<BorrowRecordView> listBorrows(Integer userId) {
        LambdaQueryWrapper<BorrowRecordView> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BorrowRecordView::getUserId, userId);
        return borrowViewMapper.selectList(queryWrapper);
    }

    /**
     * 查找符合条件，且状态为 {@code BORROWING} 的借阅记录。
     *
     * @param userId 用户ID。
     * @param bookId 书籍ID。
     * @return 如果存在此记录，则返回这条记录。
     */
    public BorrowRecord findActiveBorrowRecord(Integer userId, Integer bookId) {
        LambdaQueryWrapper<BorrowRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BorrowRecord::getUserId, userId).eq(BorrowRecord::getBookId, bookId).eq(BorrowRecord::getStatus, BorrowStatus.BORROWING);
        return this.getOne(queryWrapper);
    }

    /**
     * 将借阅记录标记为“已归还”。
     *
     * @param borrowRecordId 待标记的借阅记录ID。
     * @return 如果正确更新此记录，则返回此记录实体。
     */
    public BorrowRecord returnBook(Integer borrowRecordId) {
        BorrowRecord borrowRecord = getById(borrowRecordId);

        if (borrowRecord == null) {
            throw BusinessException.borrowRecordNotFound();
        }

        if (borrowRecord.getStatus() == BorrowStatus.RETURNED) {
            throw BusinessException.borrowRecordStatusConflict();
        }

        borrowRecord.setStatus(BorrowStatus.RETURNED);
        borrowRecord.setReturnTime(LocalDate.now());

        if (!this.updateById(borrowRecord)) {
            throw BusinessException.databaseError();
        }

        return borrowRecord;
    }

    /**
     * 获取指定用户的借阅记录数量。
     *
     * @param userId 用户ID。
     * @return 用户ID对应的用户的借阅视图中状态为 {@code BORROWING} 和 {@code OVERDUE} 的记录的数量。
     */
    public Long countBorrows(Integer userId) {
        LambdaQueryWrapper<BorrowRecordView> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(BorrowRecordView::getUserId, userId)
                .in(BorrowRecordView::getStatus, BorrowStatus.BORROWING, BorrowStatus.OVERDUE);
        return borrowViewMapper.selectCount(queryWrapper);
    }
}
